package com.example.zhuyu.basemvp.http;

import android.content.Context;
import android.net.ParseException;
import android.support.annotation.IntDef;

import com.example.zhuyu.basemvp.base.IView;
import com.example.zhuyu.basemvp.utils.CommonDialogUtil;
import com.example.zhuyu.basemvp.utils.ToastUtil;
import com.google.gson.JsonParseException;

import org.json.JSONException;

import java.io.InterruptedIOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.ConnectException;
import java.net.UnknownHostException;

import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import retrofit2.HttpException;

/**
 * @author zhuyu
 * 自定义观察者
 */
public abstract class BaseObserver<T extends BaseResponse> implements Observer<T> {
    private Disposable mDisposable;
    private CommonDialogUtil mCommonDialogUtil;
    private Context mContext;

    /**
     * 解析错误
     */
    private static final int PARSE_ERROR = 0;

    /**
     * 网络问题
     */
    private static final int BAD_NETWORK = 1;

    /**
     * 连接错误
     */
    private static final int CONNECT_ERROR = 2;
    /**
     * 连接超时
     */
    private static final int CONNECT_TIMEOUT = 3;

    /**
     * 未知错误
     */
    private static final int UNKNOWN_ERROR = 4;

    @IntDef({PARSE_ERROR, BAD_NETWORK, CONNECT_ERROR, CONNECT_TIMEOUT, UNKNOWN_ERROR})
    @Retention(RetentionPolicy.SOURCE)
    @interface ExceptionReason {
    }

    @ExceptionReason
    private int currentReason;

    public BaseObserver(IView view) {
        this.mContext = ((Context) view);
        mCommonDialogUtil = new CommonDialogUtil(mContext);
        mCommonDialogUtil.showProgress();
    }

    @Override
    public void onSubscribe(Disposable d) {

        mDisposable = d;
    }

    @Override
    public void onNext(T t) {
        if (t.isSucceeded()) {
            onHandleSuccess(t);
        } else {
            onHandleFail(t);
        }

    }

    @Override
    public void onError(Throwable e) {
        if (!mDisposable.isDisposed()) {
            mDisposable.dispose();
        }
        dismissProgress();

        if (e instanceof HttpException) {
            setReason(BAD_NETWORK);
        } else if (e instanceof ConnectException
                || e instanceof UnknownHostException) {
            //   连接错误
            setReason(CONNECT_ERROR);
        } else if (e instanceof InterruptedIOException) {
            //  连接超时
            setReason(CONNECT_TIMEOUT);
        } else if (e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof ParseException) {
            //  解析错误
            setReason(PARSE_ERROR);
        } else {
            setReason(UNKNOWN_ERROR);
        }
        onException();

    }

    private void onException() {

        @ExceptionReason int reason = getReason();
        switch (reason) {
            case CONNECT_ERROR:
                ToastUtil.showToast(mContext, "连接错误");
                break;
            case CONNECT_TIMEOUT:
                ToastUtil.showToast(mContext, "连接超时");
                break;
            case BAD_NETWORK:
                ToastUtil.showToast(mContext, "网络问题");
                break;
            case PARSE_ERROR:
                ToastUtil.showToast(mContext, "解析错误");
                break;
            case UNKNOWN_ERROR:
            default:
                ToastUtil.showToast(mContext, "未知错误");
                break;
        }

    }

    @Override
    public void onComplete() {

        if (!mDisposable.isDisposed()) {
            mDisposable.dispose();
        }
        dismissProgress();

    }

    /**
     * 消失弹出框
     */
    private void dismissProgress() {
        if (mCommonDialogUtil != null) {
            mCommonDialogUtil.dismissProgress();
        }
    }

    /**
     * 请求成功处理方法
     *
     * @param t
     */
    public abstract void onHandleSuccess(T t);

    /**
     * 请求失败处理方法
     * @param t
     */

    public abstract void onHandleFail(T t);


    private void setReason(int currentReason) {

        this.currentReason = currentReason;
    }

    /**
     * 获取请求失败原因
     *
     * @return currentReason
     */
    private int getReason() {
        return currentReason;
    }

}
